namespace xyz {
    // 约束：限制变量的数据类型
    // let a:string="qwe";
    // console.log(a)

    // let b:number=12;

    // let c:undefined;
    // console.log(c);

    // let d:null=null;
    // console.log(d)

    // any：任意类型，可以给任意类型赋值，也可以被赋值
    // unknown：任意类型，是任意类型的父集，只能被赋值，不能赋值给其他类型
    // let e:any=10;
    // let e1:string="xyz";
    // e=e1;//e="xyz"
    // let e2:number=8;
    // e2=e;
    // console.log("e",e);//xyz
    // console.log("e2",e2);//xyz

    // let f:unknown="hello";
    // let f1:string="asd";
    // f1=f;报错，不能赋值给其他类型
    // f=f1;

    // let fn=function():never{
    //     throw new Error();
    // }

    // let s:symbol=Symbol(10)
    // let s1:symbol=Symbol(10)
    // console.log(s==s1);

    // let arr:number[]=[1,2,3];//数组中只能是数字
    // let arr2:[number,string]=[1,"xyz"];//数组中第一个是数字，第二个是字符串

    // let x:string|number=7;

    // let fn=function():void{
    //     console.log(1+2);

    // }

    // function fn2():void{
    //     console.log(1+2);
    // }

    // let obj:object={
    //     name:123
    // }
    // let obj2:object=[1,2,3]
    // let obj3:object=new Set([3,4,5]);

    // 枚举
    // 默认是数字枚举
    // enum Sex {
    //     MAN,
    //     WOMAN = "女"
    // }
    // let s: Sex = Sex.MAN
    // console.log(s);//0

    // export let x: number = 10;

    // namespace:命名空间


    // 类型推论
    // let a=10;//ts推论变量a为number类型
    // a=12;

    // let b;//ts推论变量b为any任意类型

    // let c={};// c:object
    // c=[1,2,3];

    // 类型断言
    // 方法一：值 as 类型
    // 方法二：<类型>值
    // let a=123 as unknown as string;
    // a="123";

    // let b=<number>123;

    // interface(接口)：用于定义对象的类型
    // interface obj{
    //     name:string,
    //     age:number,
    //     height:number,
    //     sex?:string,//？表示该属性可选
    //     [propName:string]:unknown //任意属性，属性个数没有限制
    // }

    // let p1:obj={
    //     name:"小米",
    //     age:19,
    //     height:180,
    //     sex:"男",
    //     friends:['小红',"小明"],
    //     father:"老米"

    // }


    // interface接口可以扩展（继承）
    // interface objFather{
    //     name:string
    // }
    // interface objSon extends objFather{
    //     age:number
    // }

    // let p2:objSon={
    //     name:"小王",
    //     age:10,
    //     height:190
    // }

    // // 接口重名，接口就会合并
    // interface objSon{
    //     height:number,
    //     age:number
    // }


    // type:给类型起别名

    // 基本类型
    // type another_a=number;
    // let a:number=10;
    // let a1:another_a=10;

    // // 元祖类型
    // type another_arr=[boolean,"xyz",boolean,number];
    // let arr:another_arr=[true,"xyz",true,8];
    // let arr2:another_arr=[false,"xyz",true,8];
    // let arr3:another_arr=[true,"xyz",true,8];

    // 函数类型
    // type Fn= (x: number, y: number)=>number
    // function fn(x:number,y:number):number{
    //     let z=x+y;
    //     return z;
    // }

    // let test:Fn=(x,y)=>{
    //     let z=x+y;
    //     return z;
    // }

    // function bar(x:number,y:number):number{
    //     let z=x*y;
    //     return z;
    // }
    // let bar:Fn=(a,b)=>{
    //     return a*b;
    // }

    // type Fn2=(a:number,b:number)=>number;
    // let test:Fn2=(...args)=>{
    //     console.log(args);
    //     let sum:Fn2=(pre,next)=>{
    //         return pre*next;
    //     }
    //     let s=args.reduce(sum);
    //     return s;
    // }

    // console.log(test(1,2)) ;

    // type Fn3=(a:number,b?:number)=>number;
    // let test3:Fn3=(a,b)=>{
    //     console.log(a,b);
    //     // !非空断言
    //     return a+b!;
    // }

    // console.log(test3(12))




    // // 联合类型
    // type numStr=number|string
    // let x:numStr="2"

    // 请求数据的方法：get post GET POST
    // type method="get"| "post"| "GET" |"POST";
    // let m:method="get";

    // enum method{
    //     get="get",
    //     GET="GET",
    //     post="post",
    //     POST="POST"
    // }
    // let m:method=method.GET

    // 约束对象
    // type obj={
    //     name:string,
    //     age:number
    // } 
    // type obj2=obj&{
    //     height:number
    // }

    // let p1:obj2={
    //     name:"小米",
    //     age:19,
    //     height:190
    // }





    // type和interface的区别
    // 1.type：类型别名，可以用于基本类型、元祖类型、函数类型、联合类型
    // 2.interface：接口，只能用于对象
    // 3.type语法：type 变量=类型
    // 4.interface语法：interface 变量{}
    // 5.type起别名变量名不能重复
    // 6.interface接口名字可以重复，接口名相同，类型组合到一起
    // 7.type使用&进行扩展
    // 8.interface使用extends进行扩展

    // 使用场景的区别：
    // 1.type：基本类型、元祖类型、函数类型、联合类型的起别名
    // 2.interface：只能用于对象类型的约束


    //重载签名
    //   function add(num1: string, num2: string): string
    //   function add(num1: number, num2: number): number
    //   //实现签名
    //   function add(num1: any, num2: any): any {
    //     if (typeof num1 === 'string') {
    //       return num1 + num2 + 'aaa'
    //     } else if (typeof num1 === 'number') {
    //       return num1 + num2
    //     } else {
    //       throw new Error('错误了')
    //     }
    //   }

    //   //根据传参不同 调用的签名不同 函数实现代码的方式也不同
    //   add(1, 2)
    //   add('a', 'b')

    // class Person {
    //     //公共属性 public
    //     public name: string = '小橘猫'
    //     //私有属性 private不能被外部使用
    //     private age: number = 11
    //     //静态方法
    //     static run() { }
    //     //公共方法 原型方法
    //     public eat() {
    //         //内部可以使用私有属性 外部不行
    //         this.age
    //     }
    //     //声明属性
    //     sex: string
    //     //构造函数
    //     constructor(sex: string) {
    //         this.sex = sex
    //     }
    // }

    // //实例化
    // const p1 = new Person('女')
    // console.log(p1);
    // console.log(p1);


    // interface Smile {
    //     name?: string,//
    //     age:number,//
    //     beam(str: string): string
    //     haha(): void
    // }

    // let s:Smile={
    //     name:"小米",
    //     age:19,
    //     beam:function(str){
    //         return str+"123";
    //     },
    //     haha:()=>{}
    // }


    interface obj<x> {
        code: number,
        data: x,
    }

    interface da {
        content: string,
        url: string
    }

    type arr = [number, string];

    let res: obj<da> = {
        code: 200,
        data: {
            content: "猫猫",
            url: "http://www.baibu.com/..."
        }
    }

    let res2: obj<arr> = {
        code: 200,
        data: [12, "hello"]
    }


    function add<T,K>(a: T, b: K): T {
        return a
    }

    add<string,number>("hello",12);
    add<string|number,number>(12,12);

}

